package cn.imu.filter;

import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.IOException;

@WebFilter(filterName = "LoginFilter",
servletNames = {"LoginServlet"},
                   urlPatterns ="/*",
        initParams ={@WebInitParam(name = "logonStrings",value = "Login.jsp;index.jsp",description = "对登录页面不进行过滤"),
                @WebInitParam(name = "includeStrings",value = ".java;.jsp",description = "只对指定过滤参数后缀进行过滤"),
                @WebInitParam(name = "redirectPath",value = "/Login.jsp",description = "未通过跳转到登录界面"),
                @WebInitParam(name = "disabletestfilter",value = "N",description = "Y:过滤无效")
        } )
public class LoginFilter implements Filter {

    /*
    判断用户是否登录，未登录则退出系统
     */
    public FilterConfig config;
    /*
FilterConfig 接口
1、与普通的 Servlet 程序一样，Filter 程序也很可能需要访问 Servlet 容器。Servlet 规范将代表 ServletContext 对象和 Filter 的配置参数信息都封装到一个称为 FilterConfig 的对象中。
2、FilterConfig 接口则用于定义 FilterConfig 对象应该对外提供的方法，以便在 Filter 程序中可以调用这些方法来获取 ServletContext 对象，以及获取在 web.xml 文件中为 Filter 设置的友好名称和初始化参数。
3、FilterConfig接口定义的各个方法：
getFilterName 方法，返回 <filter-name> 元素的设置值。
getServletContext 方法，返回 FilterConfig 对象中所包装的 ServletContext 对象的引用。
getInitParameter 方法，用于返回在 web.xml 文件中为 Filter 所设置的某个名称的初始化的参数值。
getInitParameterNames 方法，返回一个 Enumeration 集合对象。
     */
    public void init(FilterConfig config) throws ServletException {
        this.config=config;
    }

    public void destroy() {
        this.config=null;
    }
    public static boolean isContains(String container, String[] regx) {
        boolean result = false;

        for (int i = 0; i < regx.length; i++) {
            if (container.indexOf(regx[i]) != -1) {
                return true;
            }
        }
        return result;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest httpServletRequest=(HttpServletRequest)request;
        //通过继承HttpServletResponseWrapper ，重写getOutputStream和getWriter方法，可以获取除静态资源之外（.jsp之类的）响应包的内容。
        HttpServletResponseWrapper wrapper=new HttpServletResponseWrapper((HttpServletResponse) response);

        String logonStrings=config.getInitParameter("logonStrings");// 登录登陆页面
        String includeStrings = config.getInitParameter("includeStrings");    // 过滤资源后缀参数
        String redirectPath = httpServletRequest.getContextPath() + config.getInitParameter("redirectPath");// 没有登陆转向页面
        String disabletestfilter = config.getInitParameter("disabletestfilter");// 过滤器是否有效

        if(disabletestfilter.toUpperCase().equals("Y")){ // 过滤无效
            chain.doFilter(request, response);
            return;
        }

        String[] logonList=logonStrings.split(";");//不进行过滤
        String[] includeList = includeStrings.split(";");//指定参数后缀过滤
        //判断请求的URL中是否包含指定后缀
        if(!this.isContains(httpServletRequest.getRequestURI(),includeList)) {// 只对指定过滤参数后缀进行过滤
            System.out.println("请求URI:"+httpServletRequest.getRequestURI());
            chain.doFilter(request, response);
            System.out.println("响应URI:"+httpServletRequest.getRequestURI());
            return;
        }
        if (this.isContains(httpServletRequest.getRequestURI(), logonList)) {// 对登录页面不进行过滤
            System.out.println("登录请求："+httpServletRequest.getRequestURI());
            chain.doFilter(request, response);
            System.out.println("登录响应："+httpServletRequest.getRequestURI());
            return;
        }
        String name=(String) httpServletRequest.getSession().getAttribute("uname");//判断用户是否登录
        if(name==null){
            wrapper.sendRedirect(redirectPath);//重定向,如果用户未登录，则跳到登录页面
        }else{
            chain.doFilter(request, response);
            return;
        }
    }
}
